package ar.edu.itba.tp1.gps.heuristics;

import ar.edu.itba.tp1.gps.api.GPSProblemImpl;
import ar.edu.itba.tp1.gps.api.GPSState;
import ar.edu.itba.tp1.gps.board.ArithmeticsRestrictions;
import ar.edu.itba.tp1.gps.board.Coordinate;

public class GPSProblemThirdHeuristic extends GPSProblemImpl {
	private ArithmeticsRestrictions restrictions;
	
	public GPSProblemThirdHeuristic(ArithmeticsRestrictions restrictions) {
		super(restrictions);
		this.restrictions = restrictions;
	}
	
	@Override
	public Integer getHValue(GPSState state) {
		int totalCant = 0;
		int freeCells = 0;
		int size = state.getValues()[0].length;
		for(int i=0; i<size; i++) {
			for(int j=0; j<size; j++) {
				if (state.getValues()[i][j] == null) {
					int cant = 0;
					freeCells++;
					for(int k=0; k<size; k++) {
						if(eval(state, i, j, k+1)) {
							cant++;
						}
					}
					totalCant += cant;
				}
			}
		}
		if (totalCant == 0 && freeCells > 0) {
			return Integer.MAX_VALUE;
		}
		return totalCant + freeCells;
	}
	
	private boolean eval(GPSState state, int i, int j, int value) {
		Integer[][] stateMatrix = state.getValues();
		if (stateMatrix[i][j] != null) {
			return false;
		}
		if(!checkRowRestriction(state, i, value)) {
			return false;
		}
		if(!checkColumnRestriction(state, j, value)) {
			return false;
		}
		if (!restrictions.checkRestriction(state, value, new Coordinate(i, j))) {
			return false;
		}
		return true;
	}
	
	private boolean checkRowRestriction(GPSState state, int i, int value) {
		Integer[][] stateMatrix = state.getValues();
		for (int j = 0; j < stateMatrix[i].length; j++) {
			if ((stateMatrix[i][j] != null) && (stateMatrix[i][j] == value)) {
				return false;
			}
		}
		return true;
	}

	private boolean checkColumnRestriction(GPSState state, int j, int value) {
		Integer[][] stateMatrix = state.getValues();
		for (int i = 0; i < stateMatrix[j].length; i++) {
			if ((stateMatrix[i][j] != null) && (stateMatrix[i][j] == value)) {
				return false;
			}
		}
		return true;
	}

}
